package com.simple.datax.flow.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.simple.datax.cache.TaskCacheBean;
import com.simple.datax.cache.model.TaskActivityState;
import com.simple.datax.cache.model.TaskState;
import com.simple.datax.flow.constants.ProcessResultConstants;
import com.simple.datax.flow.constants.TaskActivityConstants;
import com.simple.datax.flow.constants.TaskConstants;
import com.simple.datax.flow.dao.ibatis.FlowActivityDao;
import com.simple.datax.flow.dao.ibatis.FlowActivityInstanceDao;
import com.simple.datax.flow.dao.ibatis.FlowActorsDao;
import com.simple.datax.flow.dao.ibatis.FlowDao;
import com.simple.datax.flow.dao.ibatis.FlowInstanceDao;
import com.simple.datax.flow.dao.ibatis.model.Flow;
import com.simple.datax.flow.dao.ibatis.model.FlowActivity;
import com.simple.datax.flow.dao.ibatis.model.FlowActivityInstance;
import com.simple.datax.flow.dao.ibatis.model.FlowActors;
import com.simple.datax.flow.message.BaseEcMessage;
import com.simple.datax.flow.message.EcFlowMessage;
import com.simple.datax.flow.message.EcFlowRespMessage;
import com.simple.datax.flow.service.TaskActivityManager;
import com.simple.datax.flow.service.TaskManager;

/** 
 * @Title: FlowActivityInstanceManagerImpl.java 
 * @Package com.simple.datax.flow.service.impl 
 * @Description: TODO(任务活动管理器,负责任务中活动的校验,存储,查询等操作) 
 * @author tonney 
 * @date 2012-12-31 上午11:15:43 
 * @version V1.0 
 */
public class TaskActivityManagerImpl implements
		TaskActivityManager {
	public Logger log = LoggerFactory.getLogger(this.getClass());

	private FlowActivityInstanceDao flowActivityInstanceDao;

	private FlowActivityDao flowActivityDao;
	
	private FlowActorsDao flowActorsDao;
	
	private TaskCacheBean activityCache;
	
	private FlowDao flowDao;
	
	private FlowInstanceDao flowInstanceDao;
	
	public void setFlowInstanceDao(FlowInstanceDao flowInstanceDao) {
		this.flowInstanceDao = flowInstanceDao;
	}

	public void setFlowDao(FlowDao flowDao) {
		this.flowDao = flowDao;
	}

	@Override
	public void saveFlowActivityInstance(FlowActivityInstance flowActivityInstance) {
		try{
			flowActivityInstanceDao.saveFlowActivityInstance(flowActivityInstance);
			if(flowActivityInstance.getIsLast()==1){//任务结束，修改数据库状态和删除缓存
				flowInstanceDao.updateFlowInstanceStatus(flowActivityInstance.getTaskId(), TaskConstants.STATUS_SUCCESS);
				activityCache.removeAllTaskActivity(flowActivityInstance.getTaskId());
			}else{
				updateActivityStateToCache(flowActivityInstance);
			}
		}catch(Exception e){
			log.error("TaskActivityManagerImpl::saveFlowActivityInstance error=> save to DB error"+e.toString());
		}
	}
	
	/**
	 * 更新活动状态至缓存
	 * @param flowActivityInstance
	 */
	public void updateActivityStateToCache(FlowActivityInstance flowActivityInstance){
		try{
			TaskActivityState activityState = new TaskActivityState();
			activityState.setActivityNo(flowActivityInstance.getActivityNo());
			activityState.setOrder(flowActivityInstance.getActivityOrder());
			activityState.setStatus(flowActivityInstance.getStatus());
			activityState.setPrefixActNo(flowActivityInstance.getPrefixActivityNo());
			activityCache.addTaskActivityState(flowActivityInstance.getTaskId(), flowActivityInstance.getActivityNo(), activityState.toCacheString());
		}catch(Exception e){
			log.error("TaskActivityManagerImpl::updateActivityStateToCache error=> save to redis error"+e.toString());
		}
	}
	
	/**
	 * 更新活动状态至缓存
	 * @param flowActivityInstance
	 */
	public boolean isTaskOver(String taskid,String flowid){
		boolean result = true;
		int activityNum = 0;
		try{
			List<FlowActivity> activityList = flowActivityDao.getFlowActivityListByFlowTemplateid(flowid);
			if(activityList!=null){
				activityNum = activityList.size();
			}else{
				result = false;
				log.warn("TaskActivityManagerImpl::isTaskOver Flowid["+flowid+"]'s activity size is 0");
				return result;
			}
			TaskState taskState = activityCache.getTaskState(taskid);
			if(taskState==null){
				boolean isrestart = activityCache.hasRestart();
				if(isrestart){  //缓存重启过,去数据库校验活动号
					List<FlowActivityInstance> activityInstanceList = flowActivityInstanceDao.getFlowActivityInstanceListByTaskid(taskid);
					for(FlowActivityInstance activityInstance:activityInstanceList){
						if(activityInstance.getStatus()!=TaskActivityConstants.STATUS_SUCCESS){
							result = false;
							break;
						}
					}
				}else{
					result = false;
				}
			}else{
				HashMap<String, TaskActivityState> activityState = taskState.getActivityStateMap();
				if(activityState != null){
					for(Entry<String, TaskActivityState> entry:activityState.entrySet()){
						TaskActivityState activity = entry.getValue();
						if(activity.getStatus()!=TaskActivityConstants.STATUS_SUCCESS){
							result = false;
							break;
						}
					}
				}		
			}
		}catch(Exception e){
			result = false;
			log.error("TaskActivityManagerImpl::isTaskOver error=> save to redis error"+e.toString());
		}
		return result;
	}

	@Override
	public FlowActivityInstance getFlowActivityInstance(String flowid,String activity) {
		FlowActivityInstance flowActivityInstance = null;
		try{
			String activityNo = null;
			FlowActivity flowActivity = null;
			FlowActors flowActorStart = null;
			FlowActors flowActorEnd = null;
			String nextActivityNo = "";  //企业后续活动号
			String flowTemplateId = null;
			Flow flow = flowDao.getFlowById(flowid);
			if(flow!=null){
				flowTemplateId = flow.getFlowTemplateId();
			}
			if(flowTemplateId!=null&&!flowTemplateId.equals("")){
				List<FlowActivity> flowActivityList = flowActivityDao.getFlowActivityListByFlowTemplateid(flowTemplateId);
				List<FlowActors> flowActorList = flowActorsDao.getFlowActorListByFlowid(flowid);
				if(flowActorList!=null){
					for(FlowActivity fActivity:flowActivityList){
						activityNo = fActivity.getActivityNo();
						if(flowActivity == null){  //先找到活动
							if(!activityNo.isEmpty()&&activityNo.equals(activity)){
								flowActivity = fActivity;
							}else{
								continue;
							}
						}
						if(nextActivityNo==null||nextActivityNo.equals("")){  //再查找后续活动号
							if(fActivity.getActorStart().equalsIgnoreCase(flowActivity.getActorEnd())){
								nextActivityNo = fActivity.getActivityNo();
							}
						}else{  //活动和后续活动号都找到，则退出循环
							break;
						}
					}
				}
				if(flowActivity!=null){
					List<FlowActors> actors = flowActorsDao.getFlowActorListByFlowid(flowid);
					String _actorno;
					if(actors!=null){
						for(FlowActors flowActor:actors){
							_actorno = flowActor.getActorNo();
							if(!_actorno.isEmpty()){
								if(_actorno.equals(flowActivity.getActorStart())){
									flowActorStart = flowActor;
								}
								if(_actorno.equals(flowActivity.getActorEnd())){
									flowActorEnd = flowActor;
								}
							}
							if(flowActorStart!=null&&flowActorEnd!=null){
								break;
							}
						}
					}
				}
				if(flowActivity!=null&&flowActorStart!=null&&flowActorEnd!=null){
					flowActivityInstance = new FlowActivityInstance();
					flowActivityInstance.setIsLast(flowActivity.getIsLast());
					flowActivityInstance.setActivityName(flowActivity.getActivityName());
					flowActivityInstance.setActivityNo(flowActivity.getActivityNo());
					flowActivityInstance.setActivityOrder(flowActivity.getActivityOrder());
					flowActivityInstance.setActivityType(flowActivity.getActivityType());
	//				flowActivityInstance.setActorAliasFrom(flowActorStart.getActorAlias());
					flowActivityInstance.setActorIdFrom(flowActorStart.geteCode());
					flowActivityInstance.setActorIdFromAdress(flowActorStart.geteCode()+"@"+flowActorStart.geteNode());
	//				flowActivityInstance.setActorAliasTo(flowActorEnd.getActorAlias());
					flowActivityInstance.setActorTypeFrom(flowActorStart.getActorType());
					flowActivityInstance.setActorTypeTo(flowActorEnd.getActorType());
					flowActivityInstance.setActorIdTo(flowActorEnd.geteCode());
					flowActivityInstance.setActorIdToAdress(flowActorEnd.geteCode()+"@"+flowActorEnd.geteNode());
					flowActivityInstance.setCompletedDate(new Date());
					flowActivityInstance.setCreatedDate(new Date());
					flowActivityInstance.setPrefixActivityNo(flowActivity.getPrefixActivityNo());
					flowActivityInstance.setSuffixActivityNo(flowActivity.getSuffixActivityNo());
	//				flowActivityInstance.setPriority(flowActivity.getPriority());
					flowActivityInstance.setNotes(flowActivity.getNotes());
	//				flowActivityInstance.setLinkManId(flowActivity.getLinkManId());
					flowActivityInstance.setNextActivityNo(nextActivityNo);	
				}
			}
		}catch(Exception e){
			flowActivityInstance = null;
			log.error("TaskActivityManager::getFlowActivityInstance error=>"+e.toString());
		}
		return flowActivityInstance;
	}

	public int validateActivity(String senderId,String taskid,String activityNo,FlowActivityInstance factivityInstance) {
		int result = ProcessResultConstants.STATUS_SUCCESS;
		List<FlowActivityInstance> activityInstanceList = null;
		TaskActivityState taskActivityState = null;
		TaskActivityState thisActivityState = null;
		try{
			if(!senderId.equals(factivityInstance.getActorIdFrom())){
				result = ProcessResultConstants.STATUS_ACTIVITY_SENDER_UNMATCH;
				return result;
			}
			TaskState taskState = activityCache.getTaskState(taskid);
			if(taskState!=null&&taskState.getActivityStateMap()!=null){ 
				thisActivityState = taskState.getActivityStateMap().get(activityNo);
			}
			if(thisActivityState==null){  //缓存中没有此任务信息,则判断是否缓存重启过
				boolean isrestart = activityCache.hasRestart();
				/**********************************恢复缓存 BEGIN*****************************************************************/
				if(isrestart){  //缓存重启过,去数据库校验活动号
					taskState = new TaskState();					
					activityInstanceList = flowActivityInstanceDao.getFlowActivityInstanceListByTaskid(taskid);
					if(activityInstanceList!=null&&activityInstanceList.size()>0){
						for(FlowActivityInstance activityInstance:activityInstanceList){
							taskActivityState = new TaskActivityState();
							taskActivityState.setActivityNo(activityInstance.getActivityNo());
							taskActivityState.setOrder(activityInstance.getActivityOrder());
							taskActivityState.setStatus(activityInstance.getStatus());
							taskActivityState.setPrefixActNo(activityInstance.getPrefixActivityNo());
							taskActivityState.setNextActNo(activityInstance.getNextActivityNo());//设置下个活动号
							taskState.addActivityState(activityInstance.getActivityNo(), taskActivityState);
							if(activityInstance.getActivityNo().equals(activityNo)){
								if(activityInstance.getStatus()==TaskActivityConstants.STATUS_SUCCESS){  //此活动已经完成
									result = ProcessResultConstants.STATUS_ACTIVITY_OVER;
								}else if(taskActivityState.getStatus()==TaskActivityConstants.STATUS_DEALING){
									result = ProcessResultConstants.STATUS_ACTIVITY_DEALING;
								}
								thisActivityState = taskActivityState;
							}
						}
						activityCache.saveTaskState(taskid, taskState);//恢复缓存
					}
				}			
				/**********************************恢复缓存 END*****************************************************************/
			}
			/**************************************从缓存中校验活动ID BEGIN*****************************************************/
			//验证活动状态
			if(thisActivityState!=null){
				if(thisActivityState.getStatus()==TaskActivityConstants.STATUS_SUCCESS){
					result = ProcessResultConstants.STATUS_ACTIVITY_OVER;
					return result;
				}else if(thisActivityState.getStatus()==TaskActivityConstants.STATUS_DEALING){
					result = ProcessResultConstants.STATUS_ACTIVITY_DEALING;
					return result;
				}
//				result = ProcessResultConstants.STATUS_SUCCESS;
//				return result;
			}else{    //新任务中的新活动，首先判断是否传递的是第一个活动号，如果有前置活动号说明活动号不正确，验证失败
				if(factivityInstance.getPrefixActivityNo()!=null&&!factivityInstance.getPrefixActivityNo().equals("")){
					/*******************************检查前置活动是否已执行 BEGIN********************************/
					String prefixActNos = factivityInstance.getPrefixActivityNo();
					String[] prefixArray = prefixActNos.split(TaskActivityConstants.ACTIVITY_SEPRATOR);
					for(String actNo:prefixArray){
						if(taskState!=null){
							if(taskState.getActivityStateMap().get(actNo)==null||taskState.getActivityStateMap().get(actNo).getStatus()!=TaskActivityConstants.STATUS_SUCCESS){
								result = ProcessResultConstants.STATUS_ACTIVITY_PREFIX_UNOVER;
								break;
							}
						}else{    //taskState如果为null说明是新任务，新任务中首个活动应该没有前置活动，正常情况下不会走到这步
							result = ProcessResultConstants.STATUS_ACTIVITY_PREFIX_UNOVER;
							break;
						}
					}
					/*******************************检查前置活动是否已执行 END***********************************/
				}
			}
			if(thisActivityState==null&&result == ProcessResultConstants.STATUS_SUCCESS){   //本次是新活动&&并且校验前置活动成功，则设置缓存状态为处理中
				taskActivityState = new TaskActivityState();
				taskActivityState.setActivityNo(factivityInstance.getActivityNo());
				taskActivityState.setNextActNo(factivityInstance.getNextActivityNo());
				taskActivityState.setOrder(factivityInstance.getActivityOrder());
				taskActivityState.setPrefixActNo(factivityInstance.getPrefixActivityNo());
				taskActivityState.setStatus(TaskActivityConstants.STATUS_DEALING);
				activityCache.addTaskActivityState(taskid, activityNo, taskActivityState.toCacheString());
			}
			/**************************************从缓存中校验活动ID BEGIN*****************************************************/
		}catch(Exception e){
			result = ProcessResultConstants.STATUS_PROC_EXCEPTION;
			log.error("TaskActivityManager::validateActivity error=>"+e.toString());
		}
		return result;
	}
	
	public boolean recoverActivityCache(String taskid) {
		boolean result = true;
		List<FlowActivityInstance> activityInstanceList = null;
		try{
			TaskState taskState = new TaskState();
			TaskActivityState taskActivityState = null;
			activityInstanceList = flowActivityInstanceDao.getFlowActivityInstanceListByTaskid(taskid);
			if(activityInstanceList!=null){
				for(FlowActivityInstance activityInstance:activityInstanceList){
					taskActivityState = new TaskActivityState();
					taskActivityState.setActivityNo(activityInstance.getActivityNo());
					taskActivityState.setOrder(activityInstance.getActivityOrder());
					taskActivityState.setStatus(activityInstance.getStatus());
					taskActivityState.setPrefixActNo(activityInstance.getPrefixActivityNo());
					taskActivityState.setNextActNo("");//设置下个活动号
					taskState.addActivityState(activityInstance.getActivityNo(), taskActivityState);
				}
				activityCache.saveTaskState(taskid, taskState);//恢复缓存
			}
		}catch(Exception e){
			result = false;
			log.error("TaskActivityManager::recoverActivityCache error=>"+e.toString());
		}
		return result;
	}
	
	public int editMessageByFlowidAndActivityNo(String flowid,String activityNo,BaseEcMessage ecMessage,FlowActivityInstance activityInstance){
		int result = ProcessResultConstants.STATUS_SUCCESS;
		try{
			if(activityInstance!=null){
				if(ecMessage instanceof EcFlowMessage){
					EcFlowMessage ecFlowMessage = (EcFlowMessage)ecMessage;
					ecFlowMessage.getFlowMessageHead().setSenderId(activityInstance.getActorIdFrom());
					ecFlowMessage.getFlowMessageHead().setSenderAddress(activityInstance.getActorIdFromAdress());
					ecFlowMessage.getFlowMessageHead().setReceiverId(activityInstance.getActorIdTo());
					ecFlowMessage.getFlowMessageHead().setReceiverAddress(activityInstance.getActorIdToAdress());
					ecFlowMessage.getFlowMessageBody().setFlowId(flowid);
					ecFlowMessage.getFlowMessageBody().getActivityIdList().clear();
					ecFlowMessage.getFlowMessageBody().getActivityIdList().add(activityInstance.getActivityNo());
				}else if(ecMessage instanceof EcFlowRespMessage){
					EcFlowRespMessage ecFlowRespMessage = (EcFlowRespMessage)ecMessage;
					ecFlowRespMessage.getFlowRespMessageHead().setSenderId(activityInstance.getActorIdFrom());
					ecFlowRespMessage.getFlowRespMessageHead().setSenderAddress(activityInstance.getActorIdFromAdress());
					ecFlowRespMessage.getFlowRespMessageHead().setReceiverId(activityInstance.getActorIdTo());
					ecFlowRespMessage.getFlowRespMessageHead().setReceiverAddress(activityInstance.getActorIdToAdress());
					ecFlowRespMessage.getFlowRespMessageBody().getEcFlowResponseHead().setBpNo(flowid);
//					ecFlowRespMessage.getFlowRespMessageHead().getActivityIdList().clear();
//					ecFlowRespMessage.getFlowRespMessageHead().getActivityIdList().add(activityInstance.getActivityNo());
				}
			}
		}catch(Exception e){
			result = ProcessResultConstants.STATUS_EDIT_MESSAGE_EXCEPTION;
			log.error("TaskActivityManager::editMessageByFlowidAndActivityNo error=>"+e.toString());
		}
		return result;
	}	

	public void setFlowActivityDao(FlowActivityDao flowActivityDao) {
		this.flowActivityDao = flowActivityDao;
	}

	public void setFlowActorsDao(FlowActorsDao flowActorsDao) {
		this.flowActorsDao = flowActorsDao;
	}

	public void setActivityCache(TaskCacheBean activityCache) {
		this.activityCache = activityCache;
	}

	public void setFlowActivityInstanceDao(
			FlowActivityInstanceDao flowActivityInstanceDao) {
		this.flowActivityInstanceDao = flowActivityInstanceDao;
	}
}
